﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Xml;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.ComponentModel;
using System.Drawing;
using System.IO;

namespace Shoozla.DataModel
{
    public class Mp3File : INotifyPropertyChanged
    {
        private String _artist;
        private String _albumName;
        private String _title;
        private String _genre;
        private String _year;
        private Image _cover;
        private String _filename;
        private String _hash;
        private bool _dirty;
        private bool _isSelected;

        private Uri _uri;
        public event PropertyChangedEventHandler PropertyChanged;

        public Mp3File(String filename) { FileName = filename; ComputeHash(); Dirty = false; IsSelected = false; }
        public Mp3File() : this(String.Empty) { }

        public override string ToString()
        {
            return String.Format("{0} - {1} ({2}) - Cover: {3}", Artist, Title, AlbumName, HasCover);
        }

        #region Properties

        private void ComputeHash()
        {

            if (FileName != null)
            {
                MD5 alg = MD5Cng.Create();
                byte[] hash = alg.ComputeHash(System.Text.Encoding.ASCII.GetBytes(FileName.Trim()));
                string hashed = "";
                for (int i = 0; i < hash.Length; i++)
                    hashed += hash[i].ToString();
                Hash = hashed;
            }
            else
                Hash = String.Empty;
        }

        public String Hash
        {
            get { return _hash; }
            private set { _hash = value; }
        }

        public String Artist
        {
            get
            {
                return _artist;
            }
            set
            {
                if (!String.IsNullOrEmpty(value))
                {
                    _artist = value;
                    OnPropertyChanged("Artist");
                }
            }
        }

        public String AlbumName
        {
            get
            {
                return _albumName;
            }
            set
            {
                if (!String.IsNullOrEmpty(value))
                {
                    _albumName = value; 
                    OnPropertyChanged("AlbumName");
                }
            }
        }

        public String Genre
        {
            get
            {
                return _genre;
            }
            set
            {
                if (!String.IsNullOrEmpty(value))
                {
                    _genre = value;
                    OnPropertyChanged("Genre");
                }
            }
        }

        public String Year
        {
            get
            {
                return _year;
            }
            set
            {
                if (!String.IsNullOrEmpty(value))
                {
                    _year = value;
                    OnPropertyChanged("Year");
                }
            }
        }

        public String Title
        {
            get
            {
                return _title;
            }
            set
            {
                if (!String.IsNullOrEmpty(value))
                {
                    _title = value;
                    OnPropertyChanged("Title");
                }
            }
        }

        public Image Cover
        {
            get
            {
                return _cover;
            }
            set
            {
                if (value != null)
                {
                    _cover = value;
                    //Dirty = true;
                    OnPropertyChanged("Cover");
                    OnPropertyChanged("HasCover"); 
                }
            }
        }

        public BitmapImage ImageBitmap
        {
            get
            {
                if (Cover == null) return null;
                return ImageHelper.ImageToBitmapImage((Image)Cover.Clone()); }
        }

        public Uri ImageUrl
        {
            get
            {
                return _uri;
            }
            set
            {
                if (value != null)
                {
                    _uri = value;
                    OnPropertyChanged("ImageUrl"); 
                }
            }
        }

        public bool IsSelected
        {
            get
            {
                return _isSelected;
            }
            set
            {
                if (_isSelected != value)
                {
                    _isSelected = value;
                    OnPropertyChanged("IsSelected");
                }
            }
        }

        public String FileName
        {
            get
            {
                return _filename;
            }
            set
            {
                if (!String.IsNullOrEmpty(value))
                {
                    _filename = value;
                    ComputeHash();
                    OnPropertyChanged("FileName"); 
                }
            }
        }

        public bool HasCover
        {
            get
            {
                if (Cover == null)
                    return false;
                else
                    return true;
            }
        }

        public bool Dirty
        {
            get
            {
                return _dirty;
            }
            set
            {
                if (_dirty != value)
                {
                    _dirty = value;
                    OnPropertyChanged("Dirty");
                }
            }
        }

        void OnPropertyChanged(string propname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propname));
                if(propname != "Dirty")
                     Dirty = true;
            }
        }

        #endregion

        //public static readonly DependencyProperty ItemProperty = DependencyProperty.Register(
        //  "Dirty", typeof(bool), typeof(Mp3File), new PropertyMetadata(new Boolean()));

    }

    public class Cover : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private Uri _uri;
        private Image _im;
        public Uri URI
        {
            get
            {
                return _uri;
            }
            set
            {
                if (value != null)
                {
                    _uri = value;
                }
            }
        }
        private bool _dirty;
        public bool Dirty
        {
            get
            {
                return _dirty;
            }
            set
            {
                if (_dirty != value)
                {
                    _dirty = value;
                    OnPropertyChanged("Dirty");
                }
            }
        }
        public Image Image
        {
            get { return _im; }
            set
            {
                if (value != null)
                {
                    _im = value;
                    OnPropertyChanged("Image");                  
                }
            }
        }

        public BitmapImage ImageBitmap
        {
            get { return ImageHelper.ImageToBitmapImage((Image)_im.Clone()); }
        }

        public string FileName { get; set; }

        public Cover(Uri uri, string filename) { URI = uri; FileName = filename; Dirty = true; }
        public Cover(string filename) { FileName = filename; Dirty = true; }
        public Cover(Image im, string filename) { Image = im; FileName = filename; Dirty = true; }

        public override string ToString()
        {
            return "Cover: " + URI;
        }

        void OnPropertyChanged(string propname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new
                    PropertyChangedEventArgs(propname));
                if(propname != "Dirty")
                     Dirty = true;
            }
        }

    }

    public static class  ImageHelper
    {
      private static object _o = new Object();

      public static BitmapImage ImageToBitmapImage(Image im)
        {
            if (im == null)
                return new BitmapImage();
            lock (_o)
            {
                Bitmap tempIm = new Bitmap(im);

                MemoryStream ms = new MemoryStream();
                tempIm.Save(ms, im.RawFormat);
                BitmapImage bImg = new System.Windows.Media.Imaging.BitmapImage();

                bImg.BeginInit();
                bImg.StreamSource = new MemoryStream(ms.ToArray());
                bImg.CreateOptions = BitmapCreateOptions.None;
                bImg.CacheOption = BitmapCacheOption.Default;
                bImg.EndInit();

                ms.Close();
                ms = null;
                tempIm = null;

                return bImg;
            }
        }
    }
}
